using MediatR;
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Work.API.Applications.Write.Commands;
using Work.Domain.DrugManage;
using Work.ErrorCode;
using Work.Infrastructure.Interfaces;

namespace Work.API.Applications.Write.CommandHandlers
{
    /// <summary>
    /// 更新药品处理器
    /// 业务逻辑：
    /// 1. 验证药品是否存在
    /// 2. 更新药品信息
    /// 3. 如果提供了批次信息，同时更新第一条入库记录（使用事务保证原子性）
    /// </summary>
    public class UpdateDrugCommandHandler : IRequestHandler<UpdateDrugCommand, ApiResult<int>>
    {
        private readonly IBaseRepository<Drug> _drugRepo;
        private readonly IBaseRepository<DrugInbound> _inboundRepo;

        public UpdateDrugCommandHandler(
            IBaseRepository<Drug> drugRepo,
            IBaseRepository<DrugInbound> inboundRepo)
        {
            _drugRepo = drugRepo;
            _inboundRepo = inboundRepo;
        }

        public async Task<ApiResult<int>> Handle(UpdateDrugCommand request, CancellationToken cancellationToken)
        {
            var result = new ApiResult<int>();

            // 使用事务确保药品信息和入库记录的更新具有原子性
            using var transaction = await _drugRepo.DB.Database.BeginTransactionAsync(cancellationToken);
            try
            {
                // 1. 验证药品是否存在
                var drug = await _drugRepo.GetById(request.DrugId);
                if (drug == null || !drug.IsEnabled)
                {
                    result.Code = ApiEnum.失败;
                    result.Message = "药品不存在或已禁用";
                    result.Data = 0;
                    await transaction.RollbackAsync(cancellationToken);
                    return result;
                }

                // 2. 更新药品信息（不立即保存，等待事务提交）
                drug.DrugName = request.DrugName;
                drug.DrugType = request.DrugType;
                drug.CostName = request.CostName;
                drug.DosageForm = request.DosageForm;
                drug.Specification = request.Specification;
                drug.PurchasePrice = request.PurchasePrice;
                drug.SellingPrice = request.SellingPrice;
                drug.InventoryUpperLimit = request.InventoryUpperLimit;
                drug.InventoryLowerLimit = request.InventoryLowerLimit;
                drug.Efficacy = request.Efficacy;
                drug.UpdateTime = DateTime.Now;
                drug.UpdateBy = request.Operator;

                // 直接操作DbContext，不调用Repository的保存方法（避免立即提交）
                _drugRepo.DB.Set<Drug>().Update(drug);

                // 3. 如果提供了批次信息，更新第一条入库记录
                bool hasInboundUpdate = request.BatchNumber != null || 
                                        request.Supplier != null || 
                                        request.ProductionDate.HasValue || 
                                        request.ExpirationDate.HasValue;

                if (hasInboundUpdate)
                {
                    // 查询第一条入库记录（按入库日期升序，创建时间升序）
                    var firstInbound = await _inboundRepo.GetAll()
                        .Where(di => di.DrugId == request.DrugId)
                        .OrderBy(di => di.InboundDate)
                        .ThenBy(di => di.CreateTime)
                        .FirstOrDefaultAsync(cancellationToken);

                    if (firstInbound != null)
                    {
                        // 只更新提供的字段（如果为null则不更新）
                        if (request.BatchNumber != null)
                            firstInbound.BatchNumber = request.BatchNumber;
                        if (request.Supplier != null)
                            firstInbound.Supplier = request.Supplier;
                        if (request.ProductionDate.HasValue)
                            firstInbound.ProductionDate = request.ProductionDate;
                        if (request.ExpirationDate.HasValue)
                            firstInbound.ExpirationDate = request.ExpirationDate;

                        // 直接操作DbContext，不调用Repository的保存方法
                        _inboundRepo.DB.Set<DrugInbound>().Update(firstInbound);
                    }
                    // 如果没有入库记录，不报错，只更新药品信息
                }

                // 4. 统一保存（事务提交）
                await _drugRepo.DB.SaveChangesAsync(cancellationToken);
                await transaction.CommitAsync(cancellationToken);

                result.Code = ApiEnum.成功;
                result.Message = "药品信息更新成功";
                result.Data = drug.DrugId;
            }
            catch (Exception ex)
            {
                // 异常时回滚事务
                await transaction.RollbackAsync(cancellationToken);
                result.Code = ApiEnum.失败;
                result.Message = $"更新失败：{ex.Message}";
                result.Data = 0;
            }

            return result;
        }
    }
}

